#ifndef BCD6C04E_3B74_46B0_A72A_71257F8961A8
#define BCD6C04E_3B74_46B0_A72A_71257F8961A8

#include <sys/epoll.h>
#include <iostream>
#include <memory>
#include "Sock.hpp"
#include "epoller.hpp"

uint32_t EVENT_IN = (EPOLLIN);
uint32_t EVENT_OUT = (EPOLLOUT);

class epollserver : public nocopy
{
	const int num = 64;

public:
	epollserver(uint16_t &&port) : _port(port),
		listensock_ptr(new Sock()), ep_(new epoller())
	{
	}
	void Init()
	{
		listensock_ptr->Socket();
		listensock_ptr->Bind(_port);
		listensock_ptr->Listen();
		lg(Info, "listensock create and listen success");
	}
	void Accepter()
	{
		std::string clientip;
		uint16_t clientport;
		int fd = listensock_ptr->Accept(&clientip, &clientport);
		// std::cout << fd << std::endl;
		if(fd > 0)
		{
			ep_->EpollerUpdate(EPOLL_CTL_ADD, fd, EVENT_IN);
			lg(Info, "accept success,clientip:%s,clientport:%d",clientip.c_str(),clientport);
		}
	}
	void Recver(int fd)
	{
		char buffer[1024];
		int n = read(fd,buffer,sizeof(buffer)-1);
		if(n < 0){
			lg(Warnning,"read error,fd : %d",fd);
			// sleep(1);
			ep_->EpollerUpdate(EPOLL_CTL_DEL,fd,0);  // 细节三   ----- 一定要先删除再关闭对应的文件描述符
			close(fd);
		}
		else if(n == 0){
			std::cout << "client quit , Me too ,fd : " << fd << std::endl;
			ep_->EpollerUpdate(EPOLL_CTL_DEL,fd,0);
			close(fd);
		}
		else{
			buffer[n] = 0;
			std::cout << "Get a message : " << buffer << std::endl;
			std::string answer = "server response $ ";
			answer += buffer;
			int n = write(fd,answer.c_str(),answer.size());
			if(n < 0){
				lg(Warnning,"write error");
			}
		}
	}
	void Dispatcher(epoll_event resv[], int n)
	{
		for (int i = 0; i < n; i++)
		{
			int fd = resv[i].data.fd;
			uint32_t events = resv[i].events;
			if (events & EVENT_IN)
			{
				if (fd == listensock_ptr->Fd())
				{
					Accepter();
					// Printer(resv,n);  ----- resv中只有就绪的事件，有些虽然也在等待，但没有就绪，不会打印出来其文件描述符
 				}
				else
				{
					Recver(fd);
				}
			}
			else if(events & EVENT_OUT){

			}
			else{

			}
		}
		Printer(resv,n); 
	}
	void start()
	{
		int listensock = listensock_ptr->Fd();
		ep_->EpollerUpdate(EPOLL_CTL_ADD, listensock, EVENT_IN);
		for (;;)
		{
			epoll_event resv[num];
			int n = ep_->EpollerWait(resv, num);
			if (n > 0)
			{
				Dispatcher(resv, n);
			}
			else if (n == 0)
			{
				std::cout << "time out" << std::endl;
			}
			else
			{
				lg(Warnning, "epoll_wait error");
			}
		}
	}
	void Printer(epoll_event resv[],int n)
	{
		std::cout << "online lists: ";
		for(int i = 0;i < n;i++){
			int fd = resv[i].data.fd;
			std::cout << fd << " ";
		}
		std::cout << std::endl;
	}
	~epollserver()
	{
	}

private:
	std::shared_ptr<Sock> listensock_ptr;
	std::shared_ptr<epoller> ep_;
	uint16_t _port;
};

#endif /* BCD6C04E_3B74_46B0_A72A_71257F8961A8 */
